/*****************************************************************************
* @brief   SPI NAND HAL LINK
*****************************************************************************/
#include "nand_w25n.h"
#include "nand_lut.h"

/*****************************************************************************
* @brief   INFO
*****************************************************************************/
uint8_t spi_nand_read_spare(uint32_t page_addr, uint8_t *dat, uint16_t Len);

/*****************************************************************************
* @brief   hal interface link
*****************************************************************************/
char nand_spi_dev_link(nand_lut_type *lut)
{
	dword_tt id;
	char cnt;
	uu8 st[4];

	// spi nand hal link
	lut->hal.ecc_error_get = spi_nand_ecc_error_get;
	lut->hal.read_page = spi_nand_read_page;
	lut->hal.read_cache = spi_nand_read_cache;
	lut->hal.read_spare = spi_nand_read_spare;
	lut->hal.write_cache = spi_nand_write_cache;
	lut->hal.program_exe = spi_nand_program_exe;
	lut->hal.block_erase = spi_nand_block_erase;
	lut->hal.init = 0;

	// chip infomation recognize
	for (cnt = 0; cnt < 5; cnt++)
	{
		// read ID
		id.uVal = 0;
		spi_nand_read_id(id.v);

		// gd5 1Gbits
		if (id.uVal & 0xFFFF == 0xC8F1)
		{
			spi_nand_info.block_total = 1024;
			spi_nand_info.page_main_size = 2048;
			spi_nand_info.page_spare_size = 16;
			spi_nand_info.page_per_block = 64;

			lut->page_size = 2048 + 16;
			lut->page_main_size = 2048;
			lut->page_spare_size = 16;
			lut->page_per_block = 64;
			lut->block_per_plane = 1024;
			lut->block_total = 1024;
			lut->logic_block_amount = 1024 * 7 / 8;
			lut->keep_err_logic = 0;

			lut->hal.init = gd5_init;

			break;
		}

		// w25n 1Gbits
		else if ((id.uVal & 0xFFFFFF00) == 0x21AAEF00)
		{
			spi_nand_info.block_total = 1024;
			spi_nand_info.page_main_size = 2048;
			spi_nand_info.page_spare_size = 8;
			spi_nand_info.page_per_block = 64;

			lut->page_size = 2048 + 8;
			lut->page_main_size = 2048;
			lut->page_spare_size = 8;
			lut->page_per_block = 64;
			lut->block_per_plane = 1024;
			lut->block_total = 1024;
			lut->logic_block_amount = 1024 * 7 / 8;
			lut->keep_err_logic = 0;

			lut->hal.init = w25n_init;

			break;
		}
		else
		{
			spi_nand_info.block_total = 1024;
			spi_nand_info.page_main_size = 2048;
			spi_nand_info.page_spare_size = 16;
			spi_nand_info.page_per_block = 64;
		}
	}

	st[0] = spi_nand_featute_get(NAND_FEATURE_1_PROTECT);
	st[1] = spi_nand_featute_get(NAND_FEATURE_2_CFG);
	st[2] = spi_nand_featute_get(NAND_FEATURE_3_ST);

	if (st[0] != 0)
	{
		spi_nand_write_enable();
		spi_nand_featute_set(NAND_FEATURE_1_PROTECT, 0xFF, 0);
		st[0] = spi_nand_featute_get(NAND_FEATURE_1_PROTECT);
	}

	return 0;
}

/*****************************************************************************
* @brief   read spare.
* @param   page_addr, dat, Len
* @return  none
*****************************************************************************/
uint8_t spi_nand_read_spare(uint32_t page_addr, uint8_t *dat, uint16_t Len)
{
	spi_nand_read_page(page_addr);

	spi_nand_read_cache(spi_nand_info.page_main_size, dat, Len);

	return 0;
}
